package cn.wujiangbo.service.system.impl;

import cn.wujiangbo.dto.OssDto;
import cn.wujiangbo.exception.MyException;
import cn.wujiangbo.service.system.FileService;
import cn.wujiangbo.util.DateUtils;
import cn.wujiangbo.util.MyTools;
import cn.wujiangbo.vo.UploadFileVo;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.PutObjectRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;

/**
 * <p>文件上传实现类</p>
 *
 * @Author 波波老师(weixin : javabobo0513)
 */
@Service
@Slf4j
public class FileServiceOssImpl implements FileService {

    @Resource
    private OssDto ossDto;

    /**
     * 文件存储方案(1：文件本地；2：存阿里云OSS)
     */
    @Value("${file.filescheme}")
    private String filescheme;

    @Value("${server.port}")
    private String port;

    @Value("${file.download.ip}")
    private String downloadIp;

    /**
     * 上传文件
     * @param multipartFile 文件
     * @param folderName 保存文件的路径
     * @return UploadFileVo
     */
    @Override
    public UploadFileVo uploadFile(MultipartFile multipartFile, String folderName) {
        System.out.println("上传文件存储方案：" + ("1".equals(filescheme) ? "本地" : "OSS"));
        if ("1".equals(filescheme)) {
            /**
             * 注意，如果是存本地的话，files下面必须直接存文件，不能有其他层级了，否则下载时无法下载或预览图片了
             */
            //上传文件存本地方案
            if (multipartFile.isEmpty()) {
                throw new MyException("上传文件不能为空！");
            }
            //获取文件名
            String fileName = extractFilename(multipartFile);
            // 封装完整的文件路径获取方法
            String fileUploadPath = MyTools.getFileUploadPath(fileName);
            System.out.println("上传文件磁盘保存路径=" + fileUploadPath);
            try {
                java.io.File uploadFile = new java.io.File(fileUploadPath);
                java.io.File parentFile = uploadFile.getParentFile();
                if (!parentFile.exists()) {  // 如果父级不存在，也就是说files目录不存在，那么我要创建出来
                    parentFile.mkdirs();
                }
                multipartFile.transferTo(uploadFile);
            } catch (Exception e) {
                log.error("文件上传失败", e);
                throw new MyException("上传文件失败！");
            }
            String filePath = "http://" + downloadIp + ":" + port + "/file/download/" + fileName;
            System.out.println("上传文件完整访问路径=" + filePath);
            UploadFileVo vo = new UploadFileVo();
            vo.setFileName(fileName);
            vo.setFilePrefix("http://" + downloadIp + ":" + port + "/file/download/");
            vo.setFileFullPath(filePath);
            vo.setFileSize(multipartFile.getSize());
            return vo;
        } else {
            //上传文件存OSS方案
            if (ossDto.getEnable()) {
                if (multipartFile.isEmpty()) {
                    throw new MyException("上传文件不能为空！");
                }
                //获取文件名
                String fileName = extractFilename(multipartFile);
                //所有文件存储必需带上年月信息
                fileName = DateUtils.getCurrentYearMonth() + "/" + folderName + "/" + fileName;
                OSS build = new OSSClientBuilder().build(ossDto.getEndpoint(), ossDto.getAccessKey(), ossDto.getSecretKey());
                try {
                    PutObjectRequest putObjectRequest = new PutObjectRequest(ossDto.getBucketName(), fileName, multipartFile.getInputStream());
                    //将文件推到OSS服务器
                    build.putObject(putObjectRequest);
                    String imagePath = "https://" + ossDto.getBucketName() + "." + ossDto.getEndpoint() + "/" + fileName;
                    UploadFileVo vo = new UploadFileVo();
                    vo.setFileName(fileName);
                    vo.setFilePrefix("https://" + ossDto.getBucketName() + "." + ossDto.getEndpoint() + "/");
                    vo.setFileFullPath(imagePath);
                    vo.setFileSize(multipartFile.getSize());
                    return vo;
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("上传文件到阿里OSS服务器发生异常：{}", e.getMessage());
                    throw new MyException("文件上传至OSS异常！");
                } finally {
                    //关闭OSSClient
                    build.shutdown();
                }
            }
        }
        return null;
    }

    /**
     * 编码文件名，源文件名_当前时间戳
     * 如：用户上传的文件名是dog.png，那么此方法返回值为：dog_20231212112323.png
     */
    public static final String extractFilename(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        fileName = fileName.substring(0, fileName.lastIndexOf(".")) + "_" + DateUtils.getCurrentDateString(DateUtils.YYYYMMDDHHMMSS) + "." + fileName.substring(fileName.lastIndexOf(".") + 1);
        return fileName;
    }


}
